package org.taobao.ibatiside.ui.wizard;

import java.beans.PropertyChangeEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.databinding.EMFDataBindingContext;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jface.databinding.swt.ISWTObservableValue;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.part.PageBook;
import org.eclipse.wb.swt.SWTResourceManager;
import org.taobao.ibatiside.model.mapperv2.Result;
import org.taobao.ibatiside.model.mapperv2.ResultMap;
import org.taobao.ibatiside.model.mapperv2.SqlMap;
import org.taobao.ibatiside.model.mapperv2.TypeAlias;
import org.taobao.ibatiside.ui.util.ClassField;
import org.taobao.ibatiside.ui.util.MiscHelper;
import org.taobao.ibatiside.ui.util.TypeWrapper;
import org.taobao.ibatiside.ui.util.WorkspaceUtil;

public class StatementResultComposite extends PageComposite {
	Text textShowResultClassFQN;
	Button btnReusltClass;
	Button btnResultMap;
	Combo comboResultClassList;
	Combo comboResultMapList;
	Button btnCreateNewResultMap;
	private ComboViewer comboResultMapListViewer;
	private ComboViewer comboResultClassListViewer;
	private List<TypeWrapper> typeWrappers;
	private PageBook resultDetails;
	private Composite blankComposite;
	private NewResultMapComposite newResultMapComposite;
	private ShowParameterClassInfoComposite compClsInfo;
	private ShowResultMapInfoComposite resultMapInfo;
	public StatementResultComposite(Composite parent, int style) {
		super(parent, style);
	}

	public StatementResultComposite(Composite parent, int style,
			BatisCommonPage page) {
		super(parent, style, page);
	}

	@Override
	public void doNotifyChanged(Notification notification) {
		
	}

	@Override
	protected void doPropertyChange(PropertyChangeEvent evt) {
		String pn  =evt.getPropertyName();
		if (BatisSettingModel.K_SQLMAP.equals(pn)) {
			SqlMap new_map = (SqlMap) evt.getNewValue();
			comboResultMapListViewer.setInput(new_map.getResultMap());
			MiscHelper.removeAndAddNewTypeAlias(typeWrappers, new_map.getTypeAlias());
			comboResultClassListViewer.refresh();
		} else if (BatisSettingModel.K_RESULT_CLASS.equals(pn)) {
			TypeWrapper wrapper = (TypeWrapper) evt.getNewValue();
			if (wrapper != null) {
				showClass(wrapper);
			}
		}else if (BatisSettingModel.K_RESULT_MAP.equals(pn)){
			ResultMap new_map = (ResultMap) evt.getNewValue();
			if (new_map != null){
				showMap(new_map);
			}
		}
	}
	private void showMap(ResultMap new_map) {
		resultMapInfo.setResultMap(new_map);
		resultDetails.showPage(resultMapInfo);
	}

	private void showClass(TypeWrapper wrapper) {
		List<ClassField> fields = new ArrayList<ClassField>();
		String typeLiteral = wrapper.getTypeLiteral();
		int cat = wrapper.getCategory();
		if (cat == TypeWrapper.NEW_CREATE) {
			String cls_name = StringUtils
					.defaultString(WorkspaceUtil.getClassPathString(model
							.getConfigurationFile().getProject(), model
							.getBeanPath()));
			compClsInfo.setClassFQN(cls_name);
			textShowResultClassFQN.setText(cls_name);
			fields.addAll(MiscHelper.toBeClassField(model.getBeanFields()));
		} else if (cat == TypeWrapper.INTERAL) {
			ClassField uni_field = new ClassField(typeLiteral);
			uni_field.setType(typeLiteral);
			uni_field.setGetExisted(false);
			uni_field.setSetExisted(true);
			fields.add(uni_field);
			textShowResultClassFQN.setText(typeLiteral);
			compClsInfo.setClassFQN(typeLiteral);
		} else if (cat == TypeWrapper.PUBLIC) {
			try {
				IType public_type = model.getCurrentProject().findType(
						typeLiteral);
				if (public_type != null) {
					compClsInfo.setClassFQN(typeLiteral);
					textShowResultClassFQN.setText(typeLiteral);
					fields.addAll(MiscHelper.loadWritableFields(public_type));
				}
			} catch (JavaModelException e) {
				e.printStackTrace();
				setErrorMessage(e.getLocalizedMessage());
			}
		} else if (cat == TypeWrapper.TYPE_ALIAS) {
			TypeAlias alias = MiscHelper.getAliasByLiteral(model.getSqlmap(),
					typeLiteral);
			try {
				IType fqn_type = model.getCurrentProject().findType(
						alias.getType());
				if (fqn_type == null) {
					setErrorMessage("Can't load alias '" + typeLiteral);
				} else {
					String fqn_name = fqn_type.getFullyQualifiedName();
					compClsInfo.setClassFQN(fqn_name);
					textShowResultClassFQN.setText(fqn_name);
					fields.addAll(MiscHelper.loadJavaBeanFields(fqn_type));
				}
			} catch (JavaModelException e) {
				e.printStackTrace();
				setErrorMessage(e.getLocalizedMessage());
			}
		}
		model.setActiveClassFields(fields);
		compClsInfo.setFields(fields);
		resultDetails.showPage(compClsInfo);
	}

	private void initTypeWrappers() {
		typeWrappers = new ArrayList<TypeWrapper>();
		typeWrappers.add(MiscHelper.TYPEWRAPPER_INTERAL_CATEGORY);
		typeWrappers.addAll(Arrays.asList(MiscHelper.INTERAL_TYPE_WRAPPER));
		typeWrappers.add(MiscHelper.TYPEWRAPPER_SELECT_CATEGORY);
		typeWrappers.add(MiscHelper.TYPEWRAPPER_DO_CATEGORY);
		typeWrappers.add(MiscHelper.TYPEWRAPPER_ALIAS_CATEGORY);
	}
	@Override
	protected void createContent() {
		initTypeWrappers();
		setLayout(new GridLayout(1, false));
		Group group = new Group(this, SWT.NONE);
		GridData gd_group = new GridData(SWT.FILL, SWT.TOP, true, false, 1, 1);
		gd_group.heightHint = 65;
		group.setLayoutData(gd_group);
		group.setText("Result Output");
		group.setBounds(0, 0, 70, 84);
		group.setLayout(new FormLayout());
		
		btnReusltClass = new Button(group, SWT.RADIO);
		btnReusltClass.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				model.setResultRequired(true);
				model.setResultUseClass(true);
			}
		});
		btnReusltClass.setText("To Class");
		FormData fd_btnReusltClass = new FormData();
		fd_btnReusltClass.top = new FormAttachment(0, 3);
		fd_btnReusltClass.right = new FormAttachment(20);
		fd_btnReusltClass.left = new FormAttachment(0);
		btnReusltClass.setLayoutData(fd_btnReusltClass);
		
		comboResultClassListViewer = new ComboViewer(group, SWT.NONE);
		comboResultClassListViewer.addSelectionChangedListener(new ISelectionChangedListener() {
			public void selectionChanged(SelectionChangedEvent event) {
				if (!event.getSelection().isEmpty()){
					TypeWrapper selected_wrapper = (TypeWrapper) ((IStructuredSelection) event
							.getSelection()).getFirstElement();
					TypeWrapper detailWrapper = MiscHelper.getDetailWrapper(getShell(), selected_wrapper);
					if (detailWrapper != null) model.setResultClass(detailWrapper);
				}
			}
		});
		FormData fd_comboResultClassList = new FormData();
		fd_comboResultClassList.right = new FormAttachment(50);
		fd_comboResultClassList.left = new FormAttachment(btnReusltClass);
		
		
		comboResultClassList = comboResultClassListViewer.getCombo();
		comboResultClassList.setLayoutData(fd_comboResultClassList);
		
		textShowResultClassFQN = new Text(group, SWT.BORDER);
		textShowResultClassFQN.setForeground(SWTResourceManager.getColor(SWT.COLOR_RED));
		textShowResultClassFQN.setEditable(false);
		FormData fd_textShowResultClassFQN = new FormData();
		fd_textShowResultClassFQN.left = new FormAttachment(comboResultClassList, 10);
		fd_textShowResultClassFQN.right = new FormAttachment(100);
		textShowResultClassFQN.setLayoutData(fd_textShowResultClassFQN);
		
		btnResultMap = new Button(group, SWT.RADIO);
		btnResultMap.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				model.setResultRequired(true);
				model.setResultUseClass(false);
			}
		});
		btnResultMap.setText("To ResultMap");
		FormData fd_btnResultMap = new FormData();
		fd_btnResultMap.top = new FormAttachment(btnReusltClass, 10);
		fd_btnResultMap.left = new FormAttachment(0);
		btnResultMap.setLayoutData(fd_btnResultMap);
		
		comboResultMapListViewer = new ComboViewer(group, SWT.NONE);
		comboResultMapListViewer.addSelectionChangedListener(new ISelectionChangedListener() {
			public void selectionChanged(SelectionChangedEvent event) {
				if (!event.getSelection().isEmpty()){
					model.setResultMap((ResultMap) ((IStructuredSelection)event.getSelection()).getFirstElement());
				}
			}
		});
		comboResultMapList = comboResultMapListViewer.getCombo();
		FormData fd_comboResultMapList = new FormData();
		fd_comboResultMapList.top = new FormAttachment(comboResultClassList, 5);
		fd_comboResultMapList.right = new FormAttachment(50);
		fd_comboResultMapList.left = new FormAttachment(comboResultClassList, 0, SWT.LEFT);
		comboResultMapList.setLayoutData(fd_comboResultMapList);
		
		btnCreateNewResultMap = new Button(group, SWT.NONE);
		btnCreateNewResultMap.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				newResultMapComposite.renew();
				resultDetails.showPage(newResultMapComposite);
				btnCreateNewResultMap.setEnabled(false);
			}
		});
		btnCreateNewResultMap.setText("Create ResultMap");
		FormData fd_btnCreateNewResultMap = new FormData();
		fd_btnCreateNewResultMap.top = new FormAttachment(0, 29);
		fd_btnCreateNewResultMap.left = new FormAttachment(comboResultMapList, 10);
		btnCreateNewResultMap.setLayoutData(fd_btnCreateNewResultMap);
		
		resultDetails = new PageBook(this, SWT.NONE);
		resultDetails.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
		
		blankComposite = new Composite(resultDetails, SWT.NONE);
		newResultMapComposite = new NewResultMapComposite(resultDetails, SWT.NONE, this.hostPage){

			@Override
			public void okPressed() {
				ResultMap new_resultmap = newResultMapComposite.newResultMap;
				model.getSqlmap().getResultMap().add(new_resultmap);
				comboResultMapListViewer.refresh();
				comboResultMapListViewer.setSelection(new StructuredSelection(new_resultmap));
				btnCreateNewResultMap.setEnabled(true);
			}

			@Override
			public void cancelPressed() {
				resultDetails.showPage(blankComposite);
				btnCreateNewResultMap.setEnabled(true);
			}
			
		};
		comboResultClassListViewer.setContentProvider(new ArrayContentProvider());
		comboResultClassListViewer.setLabelProvider(new TypeWrapperLabelProvider());
		comboResultClassListViewer.setInput(typeWrappers);
		comboResultMapListViewer.setContentProvider(new ArrayContentProvider());
		comboResultMapListViewer.setLabelProvider(new LabelProvider(){
			@Override
			public String getText(Object element) {
				return ((ResultMap)element).getId();
			}
		});
		compClsInfo = new ShowParameterClassInfoComposite(resultDetails, SWT.NONE);
		resultMapInfo = new ShowResultMapInfoComposite(resultDetails, SWT.NONE);
	}
	@Override
	protected void doBinding(EMFDataBindingContext bindingContext) {
		super.doBinding(bindingContext);
		ISWTObservableValue ob_control_resultclass = SWTObservables.observeEnabled(comboResultClassList);
		ISWTObservableValue ob_selection_resultclass = SWTObservables.observeSelection(btnReusltClass);
		bindingContext.bindValue(ob_control_resultclass, ob_selection_resultclass);
		
		ISWTObservableValue ob_control_resultmap_select = SWTObservables.observeEnabled(comboResultMapList);
		ISWTObservableValue ob_selection_resultmap = SWTObservables.observeSelection(btnResultMap);
		bindingContext.bindValue(ob_control_resultmap_select, ob_selection_resultmap);
		
		ISWTObservableValue ob_control_resultmap_create = SWTObservables.observeEnabled(btnCreateNewResultMap);
		bindingContext.bindValue(ob_control_resultmap_create, ob_selection_resultmap);
		
	}
}
